// Copyright (c) 2022 CHANGLEI. All rights reserved.

import 'package:aircraft_war/bloc/game_state_cubit.dart';
import 'package:aircraft_war/generated/assets.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:flame_audio/flame_audio.dart';

/// Created by changlei on 2022/5/20.
///
/// 处理音效
class Sounds {
  Sounds._();

  GameState _state = GameState.idle;

  /// 背景音乐
  static final bgm = Sounds._();

  static bool _isMute = false;

  /// 是否静音
  static bool get isMute => _isMute;

  /// 空闲中
  Future<void> setup() async {
    FlameAudio.audioCache.prefix = Assets.audios('');
    FlameAudio.bgm.initialize();
    _state = GameState.idle;
  }

  /// 等待中
  Future<void> pending() async {
    await _playBgm(Audios.s2);
    _state = GameState.pending;
  }

  /// 运行
  Future<void> run() async {
    if (_state == GameState.pausing) {
      await _resumeBgm();
    } else {
      await _playBgm(Audios.game_music, volume: 0.5);
    }
    _state = GameState.running;
  }

  /// 暂停中
  Future<void> pause() async {
    await FlameAudio.bgm.pause();
    _state = GameState.pausing;
  }

  /// 已结束
  Future<void> stop() async {
    if (_state != GameState.stopped) {
      await gameOver();
    }
    await _playBgm(Audios.s4);
    _state = GameState.stopped;
  }

  /// 关闭
  Future<void> dispose() async {
    FlameAudio.bgm.dispose();
    _state = GameState.stopped;
  }

  static Future<void> _playBgm(String filename, {double volume = 1.0}) async {
    if (_isMute) {
      return;
    }
    return FlameAudio.bgm.play(filename, volume: volume);
  }

  static Future<void> _resumeBgm() async {
    if (_isMute) {
      return;
    }
    return FlameAudio.bgm.resume();
  }

  static final _players = <String, AudioPlayer>{};

  /// 加载缓存
  static Future<void> loadCaches() {
    return FlameAudio.audioCache.loadAll([
      Audios.s2,
      Audios.s4,
      Audios.game_music,
      Audios.get_double_laser,
      Audios.get_bomb,
      Audios.small_enemy_down,
      Audios.large_enemy_down,
      Audios.middle_enemy_down,
      Audios.bullet,
      Audios.use_bomb,
      Audios.out_porp,
      Audios.game_over,
      Audios.button,
      Audios.big_spaceship_flying,
    ]);
  }

  /// 清除缓存
  static Future<void> clearCaches() {
    return FlameAudio.audioCache.clearAll();
  }

  /// 销毁
  static Future<void> disposePlayers() async {
    final players = List.of(_players.values);
    _players.clear();
    await Future.wait(players.map((e) => e.dispose()));
  }

  /// 静音
  static Future<void> mute(bool mute) async {
    if (_isMute == mute) {
      return;
    }
    _isMute = mute;
    if (_isMute) {
      await FlameAudio.bgm.stop();
      await disposePlayers();
    } else {
      switch (Sounds.bgm._state) {
        case GameState.idle:
          await Sounds.bgm.setup();
          break;
        case GameState.pending:
          await Sounds.bgm.pending();
          break;
        case GameState.running:
          await Sounds.bgm.run();
          break;
        case GameState.pausing:
          await Sounds.bgm.pause();
          break;
        case GameState.stopped:
          await Sounds.bgm.stop();
          break;
      }
    }
  }

  /// 获取双子弹
  static Future<void> getBulletSupply() async {
    await _play(Audios.get_double_laser);
  }

  /// 获取炸弹
  static Future<void> getFirepowerSupply() async {
    await _play(Audios.get_bomb);
  }

  /// 摧毁小飞机
  static Future<void> smallEnemyDown() async {
    await _play(Audios.small_enemy_down);
  }

  /// 摧毁中飞机
  static Future<void> middleEnemyDown() async {
    await _play(Audios.middle_enemy_down);
  }

  /// 摧毁打飞机
  static Future<void> largeEnemyDown() async {
    await _play(Audios.large_enemy_down);
  }

  /// 发射子弹
  static Future<void> useBullet() async {
    await _play(
      Audios.bullet,
      volume: 0.3,
      priorityOfUseCaches: true,
    );
  }

  /// 使用炸弹
  static Future<void> useFirepowerSupply() async {
    await _play(Audios.use_bomb);
  }

  /// 使用双子弹
  static Future<void> useBulletSupply() async {
    await _play(
      Audios.out_porp,
      volume: 0.3,
      priorityOfUseCaches: true,
    );
  }

  /// 游戏结束
  static Future<void> gameOver() async {
    await _play(Audios.game_over);
  }

  /// 点击按钮
  static Future<void> button() async {
    await _play(Audios.button);
  }

  /// 大飞机飞
  static Future<AudioPlayer> bigSpaceshipFlying() {
    return FlameAudio.loop(Audios.big_spaceship_flying);
  }

  static Future<void> _play(String file, {double volume = 1.0, bool priorityOfUseCaches = false}) async {
    if (_isMute) {
      return;
    }
    final player = _players[file];
    if (player == null || !priorityOfUseCaches) {
      await _players.remove(file)?.dispose();
      _players[file] = await FlameAudio.play(file, volume: volume);
    } else if (player.state != PlayerState.playing) {
      await player.setVolume(volume);
      await player.play(AssetSource(file));
    }
  }
}
